home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / admin / fsutil_1.z / fsutil_1 / fsutil / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-20  |  6.2 KB  |  298 lines

  1. /*
  2.  * fs-util    A simple generic frontend for the for the fsck and mkfs
  3.  *        programs under Linux.  See the manual pages for details.
  4.  *
  5.  * Usage:    fsck [-AV] [-t fstype] [fs-options] device
  6.  *        mkfs [-V] [-t fstype] [fs-options] device< [size]
  7.  *
  8.  * Authors:    David Engel, <david@ods.com>
  9.  *        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  10.  */
  11.  
  12.  
  13. #include <sys/types.h>
  14. #include <sys/wait.h>
  15. #include <errno.h>
  16. #include <limits.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <errno.h>
  21. #include <mntent.h>
  22. #include <unistd.h>
  23. #include <getopt.h>
  24.  
  25.  
  26. #ifndef DEFAULT_FSTYPE
  27. #   define DEFAULT_FSTYPE    "minix"
  28. #endif
  29.  
  30. #define _PATH_PROG    "%s.%s"
  31. #define _PROG_FSCK    "fsck"
  32.  
  33. #define EXIT_OK          0
  34. #define EXIT_NONDESTRUCT 1
  35. #define EXIT_DESTRUCT    2
  36. #define EXIT_UNCORRECTED 4
  37. #define EXIT_ERROR       8
  38. #define EXIT_USAGE       16
  39. #define EXIT_LIBRARY     128
  40.  
  41. static char *Version = "1.8";
  42. static char *ignored_types[] = {
  43.   "ignore",
  44.   "iso9660",
  45.   "msdos",
  46.   "nfs",
  47.   "proc",
  48.   "sw",
  49.   "swap",
  50.   NULL
  51. };
  52.  
  53.  
  54. /* Execute a program. */
  55. int do_exec(char *prog, char **argv, int verbose)
  56. {
  57.     char *args[33];
  58.     register int i;
  59.     int pid, status;
  60.  
  61.     /* Build the vector. */
  62.     i = 0;
  63.     args[i++] = prog;
  64.     while(*argv != NULL && i < 32)
  65.         args[i++] = *argv++;
  66.     args[i] = NULL;
  67.  
  68.     if (verbose) {
  69.     i = 0;
  70.     while(args[i] != NULL) {
  71.         printf("%s ", args[i]);
  72.         i++;
  73.     }
  74.     printf("\n");
  75.     if (verbose > 1)
  76.         return EXIT_OK;
  77.     }
  78.  
  79.     /* Fork and execute the correct program. */
  80.     if ((pid = fork()) < 0) {
  81.         perror("fork");
  82.     status = EXIT_ERROR;
  83.     } else if (pid == 0) {
  84.     (void) execvp(args[0], args);
  85.       perror(args[0]);
  86.     exit(EXIT_ERROR);
  87.     } else {
  88.         while(wait(&status) != pid)
  89.         ;
  90.     status = WEXITSTATUS(status);
  91.     }
  92.  
  93.     return status;
  94. }
  95.  
  96.  
  97. /* Check if we have to ignore a file system type. */
  98. int ignore(char *type, char *opts)
  99. {
  100.     char *cp;
  101.     char **ip;
  102.  
  103.     ip = ignored_types;
  104.     while (*ip != NULL) {
  105.     if (!strcmp(type, *ip))
  106.         return 1;
  107.     ip++;
  108.     }
  109.  
  110.     for (cp = strtok(opts, ","); cp != NULL; cp = strtok(NULL, ",")) {
  111.     if (!strcmp(cp, "noauto"))
  112.         return 1;
  113.     }
  114.  
  115.     return 0;
  116. }
  117.  
  118.  
  119. /* Check all file systems, using the /etc/fstab table. */
  120. int check_all(int verbose, char **argv)
  121. {
  122.     char path[PATH_MAX];
  123.     char *args[33];
  124.     FILE *mntfile;
  125.     struct mntent *mp;
  126.     register int i;
  127.     int status = EXIT_OK;
  128.  
  129.     if (verbose)
  130.         printf("Checking all file systems.\n");
  131.  
  132.     /* Create an array of arguments. */
  133.     i = 0;
  134.     while (*argv != NULL && i < 32)
  135.     args[i++] = *argv++;
  136.     args[i] = NULL;
  137.     args[i + 1] = NULL;
  138.  
  139.     /* Open the mount table. */
  140.     if ((mntfile = setmntent(MNTTAB, "r")) == NULL) {
  141.     perror(MNTTAB);
  142.     exit(EXIT_ERROR);
  143.     }
  144.  
  145.     /* Walk through the /etc/fstab file. */
  146.     while ((mp = getmntent(mntfile)) != NULL) {
  147.     if (verbose)
  148.         printf("%-7s %-15s %-15s ", mp->mnt_type,
  149.            mp->mnt_fsname, mp->mnt_dir);
  150.     if (ignore(mp->mnt_type, mp->mnt_opts)) {
  151.         if (verbose)
  152.             printf("(ignored)\n");
  153.         continue;
  154.     }
  155.  
  156.     /* Build program name. */
  157.     sprintf(path, _PATH_PROG, _PROG_FSCK, mp->mnt_type);
  158.     args[i] = mp->mnt_fsname;
  159.     status |= do_exec(path, args, verbose);
  160.     }
  161.  
  162.     (void) endmntent(mntfile);
  163.  
  164.     return status;
  165. }
  166.  
  167.  
  168. /* Lookup filesys in /etc/fstab and return the corresponding entry. */
  169. struct mntent *lookup(char *filesys)
  170. {
  171.     FILE *mntfile;
  172.     struct mntent *mp;
  173.  
  174.     /* No filesys name given. */
  175.     if (filesys == NULL)
  176.         return NULL;
  177.  
  178.     /* Open the mount table. */
  179.     if ((mntfile = setmntent(MNTTAB, "r")) == NULL) {
  180.     perror(MNTTAB);
  181.     exit(EXIT_ERROR);
  182.     }
  183.  
  184.     while ((mp = getmntent(mntfile)) != NULL) {
  185.     if (!strcmp(filesys, mp->mnt_fsname) ||
  186.         !strcmp(filesys, mp->mnt_dir))
  187.         break;
  188.     }
  189.  
  190.     (void) endmntent(mntfile);
  191.  
  192.     return mp;
  193. }
  194.  
  195.  
  196. void usage(int fsck, char *prog)
  197. {
  198.     if (fsck) {
  199.     fprintf(stderr, "Usage: fsck [-AV] [-t fstype] [fs-options] filesys\n");
  200.     } else {
  201.     fprintf(stderr, "Usage: mkfs [-V] [-t fstype] [fs-options] filesys [size]\n");
  202.     }
  203.  
  204.     exit(EXIT_USAGE);
  205. }
  206.  
  207.  
  208. void main(int argc, char *argv[])
  209. {
  210.     char path[PATH_MAX];
  211.     char *oldpath, newpath[PATH_MAX];
  212.     register char *sp;
  213.     struct mntent *fsent;
  214.     char *fstype = NULL;
  215.     int verbose = 0;
  216.     int doall = 0;
  217.     int i, fsck, more;
  218.  
  219.     /* Must be 1 for "fsck" and 0 for "mkfs". */
  220.     if ((sp = strrchr(argv[0], '/')) != NULL)
  221.         sp++;
  222.     else
  223.         sp = argv[0];
  224.     if (!strcmp(sp, _PROG_FSCK))
  225.         fsck = 1;
  226.     else
  227.         fsck = 0;
  228.  
  229.     /* Check commandline options. */
  230.     opterr = 0;
  231.     more = 0;
  232.     while ((more == 0) && ((i = getopt(argc, argv, "AVt:")) != EOF))
  233.     switch(i) {
  234.       case 'A':
  235.         doall++;
  236.         break;
  237.       case 'V':
  238.         verbose++;
  239.         break;
  240.       case 't':
  241.         if (optarg == NULL)
  242.             usage(fsck, sp);
  243.         fstype = optarg;
  244.         break;
  245.       default:
  246.         more = 1;
  247.         break;        /* start of specific arguments */
  248.     }
  249.  
  250.     /* Did we get any specific arguments? */
  251.     if (more)
  252.         optind--;
  253.  
  254.     /* Print our version number if requested. */
  255.     if (verbose)
  256.         printf("%s (fsutil) version %s (%s)\n", argv[0],
  257.            Version, __DATE__);
  258.  
  259.     /* Update our PATH to include /etc/fs and /etc. */
  260.     strcpy(newpath, "PATH=/etc/fs:/etc:");
  261.     if ((oldpath = getenv("PATH")) != NULL)
  262.         strcat(newpath, oldpath);
  263.     putenv(newpath);
  264.     
  265.     /* If -A was specified ("check all"), double-check. */
  266.     if (doall) {
  267.     if (!fsck || (fstype != NULL))
  268.         usage(fsck, sp);
  269.     exit(check_all(verbose, &argv[optind]));
  270.     } else {
  271.     /* If -t wasn't specified, we must deduce fstype. */
  272.     if (fstype == NULL) {
  273.         /* make sure that "filesys" was specified */
  274.         if (optind >= argc)
  275.         usage(fsck, sp);
  276.         /* then try looking for it in /etc/fstab */
  277.         if ((fsent = lookup(argv[argc - 1])) != NULL) {
  278.             argv[argc - 1] = fsent->mnt_fsname;
  279.         fstype = fsent->mnt_type;
  280.         } else {
  281.             if (!fsck && optind < argc-1) {
  282.             if ((fsent = lookup(argv[argc - 2])) != NULL) {
  283.                 argv[argc - 2] = fsent->mnt_fsname;
  284.             fstype = fsent->mnt_type;
  285.             }
  286.         }
  287.         }
  288.         /* if we still don't know, use the default */
  289.         if (fstype == NULL) fstype = DEFAULT_FSTYPE;
  290.     }
  291.  
  292.     /* Build program name. */
  293.     sprintf(path, _PATH_PROG, sp, fstype);
  294.     exit(do_exec(path, &argv[optind], verbose));
  295.     }
  296.     /*NOTREACHED*/
  297. }
  298.